using System.Collections.ObjectModel;
using FileTransfer.Client.Http.Model;

namespace FileTransferDesktop.ViewModels.Dialogs;

public partial class FileItemViewModel : ObservableObject
{
    [ObservableProperty]
    private bool _isSelected;

    [ObservableProperty]
    private string _fileName = string.Empty;

    [ObservableProperty]
    private string _fileSize = string.Empty;

    [ObservableProperty]
    private string _md5 = string.Empty;

    public File File { get; set; } = null!;
}

public partial class FileSelectionDialogViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<FileItemViewModel> _files = [];

    [ObservableProperty]
    private string _shareCode = string.Empty;

    [ObservableProperty]
    private string _messages = string.Empty;

    [ObservableProperty]
    private string _createTime = string.Empty;

    [ObservableProperty]
    private string _expiryTime = string.Empty;

    [ObservableProperty]
    private bool? _allSelected = false;

    private bool _isUpdatingByCode = false;

    public Action<List<File>>? OnConfirmSelection { get; set; }
    public event EventHandler<bool>? RequestClose;

    public void SetShareInfo(ShareItem shareItem)
    {
        ShareCode = shareItem.Code;
        CreateTime = shareItem.CreateTime.ToString("yyyy-MM-dd HH:mm:ss");
        if (shareItem.ExpiryTime.Year > 1)
            ExpiryTime = shareItem.ExpiryTime.ToString("yyyy-MM-dd HH:mm:ss");

        // 设置留言
        if (shareItem.Messages?.Any() == true)
        {
            Messages = string.Join(
                "\n",
                shareItem.Messages.Select(m => $"[{m.CreatedAt:MM-dd HH:mm}] {m.Content}")
            );
        }
        else
        {
            Messages = "无留言";
        }

        // 设置文件列表
        Files.Clear();
        if (shareItem.Files?.Any() == true)
        {
            foreach (var file in shareItem.Files)
            {
                var fileItem = new FileItemViewModel
                {
                    File = file,
                    FileName = file.FileName,
                    FileSize = FormatFileSize(file.FileSize),
                    Md5 = file.Md5,
                    IsSelected = true, // 默认选中所有文件
                };
                fileItem.PropertyChanged += FileItem_PropertyChanged;
                Files.Add(fileItem);
            }
        }

        UpdateAllSelectedState();
    }

    private void FileItem_PropertyChanged(
        object? sender,
        System.ComponentModel.PropertyChangedEventArgs e
    )
    {
        if (e.PropertyName == nameof(Dialogs.FileItemViewModel.IsSelected))
        {
            UpdateAllSelectedState();
        }
    }

    partial void OnAllSelectedChanged(bool? oldValue, bool? newValue)
    {
        if (_isUpdatingByCode)
            return;

        if (!oldValue.HasValue)
        {
            AllSelected = true;
            return;
        }

        switch (newValue)
        {
            case false:
                foreach (var file in Files)
                    file.IsSelected = false;
                break;
            case true:
                foreach (var file in Files)
                    file.IsSelected = true;
                break;
        }
    }

    private void UpdateAllSelectedState()
    {
        _isUpdatingByCode = true;

        try
        {
            if (Files.Count == 0)
            {
                AllSelected = false;
                return;
            }

            var selectedCount = Enumerable.Count<FileItemViewModel>(Files, f => f.IsSelected);

            if (selectedCount == Files.Count)
            {
                AllSelected = true;
            }
            else if (selectedCount == 0)
            {
                AllSelected = false;
            }
            else
            {
                AllSelected = null;
            }
        }
        finally
        {
            _isUpdatingByCode = false;
        }
    }

    [RelayCommand]
    private void Confirm()
    {
        var selectedFiles = Files
            .Where<FileItemViewModel>(f => f.IsSelected)
            .Select(f => f.File)
            .ToList();

        if (selectedFiles.Count == 0)
        {
            // 可以显示一个提示消息
            return;
        }

        OnConfirmSelection?.Invoke(selectedFiles);
        RequestClose?.Invoke(this, true);
    }

    [RelayCommand]
    private void Cancel()
    {
        RequestClose?.Invoke(this, false);
    }

    private static string FormatFileSize(long bytes)
    {
        const long kb = 1024;
        const long mb = kb * 1024;
        const long gb = mb * 1024;

        return bytes switch
        {
            >= gb => $"{bytes / (double)gb:F2} GB",
            >= mb => $"{bytes / (double)mb:F2} MB",
            >= kb => $"{bytes / (double)kb:F2} KB",
            _ => $"{bytes} B",
        };
    }
}
